// CherryMerry ( Mikhail Tomilenko ), Reverse Entertainment, 2021-2024


#include "../Public/PlayerMovementManager.h"

#include <NifestGame/Core/Public/NF_Character.h>
#include <NifestGame/ActorComponents/Public/PlayerUIManager.h>

#include <Kismet/GameplayStatics.h>
#include "Runtime/Engine/Public/TimerManager.h"


UPlayerMovementManager::UPlayerMovementManager()
{

	PrimaryComponentTick.bCanEverTick = true;

	MaxRunSpeed = 600.f;
	MaxCrouchedRunSpeed = 450.f;
	MaxWalkSpeed = 300.f;
	MaxCrouchedWalkSpeed = 240.f;

	MaxStamina = 100.f;
	CurrentStamina = MaxStamina;

	DashDistance = 6000.f;
}


void UPlayerMovementManager::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	UpdateStamina();
}

void UPlayerMovementManager::BeginPlay()
{
	Super::BeginPlay();

	bIsCrouching = false;
	bIsRunning = false;
}

void UPlayerMovementManager::UpdateStamina()
{
	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);
	UPlayerUIManager* UIManager = Character->FindComponentByClass<UPlayerUIManager>();

	if (bIsRunning || bBlockingDamage)
	{
		CurrentStamina -= StaminaDrainTime;
		CurrentRefillDelayTime = DelayBeforeRefill;
		UIManager->PlayerHUDMenu->PlayerStaminaWidget->UpdateWidgetInfo(CurrentStamina, MaxStamina);
	}

	if (!bIsRunning || !bBlockingDamage && CurrentStamina < MaxStamina)
	{
		CurrentRefillStaminaDelay--;
		if (CurrentRefillStaminaDelay <= 0)
		{
			CurrentStamina += StaminaRefillTime;
			UIManager->PlayerHUDMenu->PlayerStaminaWidget->UpdateWidgetInfo(CurrentStamina, MaxStamina);
		}
	}

	if (CurrentStamina <= 0)
	{
		bHasStamina = false;

		if (bIsRunning)
		{
			StopSprinting();
		}
	}
	else
	{
		bHasStamina = true;
	}
}

void UPlayerMovementManager::UseStamina(float AmountToUse)
{
	if (CurrentStamina <= 0)
	{
		CurrentStamina -= AmountToUse;
	}
}

void UPlayerMovementManager::StartSprinting()
{
	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);

	if (bHasStamina)
	{
		if (!bIsCrouching)
		{
			if (Character->GetVelocity().Size() >= 0.5)
			{
				UE_LOG(LogTemp, Warning, TEXT("Sprint"))
				II_Core* CoreInterface = Cast<II_Core>(GetOwner());

				if (CoreInterface && !bIsRunning)
				{
					CoreInterface->Execute_UpdatePlayerSpeed(GetOwner(), MaxRunSpeed, false);
					bIsRunning = true;
				}
			}
			else
			{
				bIsRunning = false;
			}
		}
		else
		{
			if (Character->GetVelocity().Size() >= 0.5)
			{
				UE_LOG(LogTemp, Warning, TEXT("Sprint"))
				II_Core* CoreInterface = Cast<II_Core>(GetOwner());

				if (CoreInterface && !bIsRunning)
				{
					CoreInterface->Execute_UpdatePlayerSpeed(GetOwner(), MaxCrouchedRunSpeed, true);
					bIsRunning = true;
				}
			}
			else
			{
				bIsRunning = false;
			}
		}
	}
	
}

void UPlayerMovementManager::StopSprinting()
{
	II_Core* CoreInterface = Cast<II_Core>(GetOwner());

	if (CoreInterface && bIsRunning)
	{
		UE_LOG(LogTemp, Warning, TEXT("not Sprint"))
		CoreInterface->Execute_UpdatePlayerSpeed(GetOwner(), MaxCrouchedWalkSpeed, true);
		CoreInterface->Execute_UpdatePlayerSpeed(GetOwner(), MaxWalkSpeed, false);
		bIsRunning = false;
	}
}

void UPlayerMovementManager::StartCrouching()
{
	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);

	if (Character->CanCrouch() && !bIsCrouching)
	{
		UE_LOG(LogTemp, Warning, TEXT("Crouched"))
		Character->Crouch();
		bIsCrouching = true;
		if (bIsRunning)
		{
			StartSprinting();
		}
	}
}

void UPlayerMovementManager::StopCrouching()
{
	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);

	if (bIsCrouching)
	{
		UE_LOG(LogTemp, Warning, TEXT("UnCrouched"))
		Character->UnCrouch();
		bIsCrouching = false;
		if (bIsRunning)
		{
			StartSprinting();
		}
	}
}

void UPlayerMovementManager::Dash()
{
	ACharacter* Character = UGameplayStatics::GetPlayerCharacter(GetWorld(), 0);

	const FVector ForwardDir = Character->GetControlRotation().Vector();
	Character->LaunchCharacter(ForwardDir * DashDistance, true, true);
}
